function Debug( text ){
	if( console ){
		return console.log(text);
	}
	e = document.getElementById('debug') 
	e.value = text + "\n_________________________\n" + e.value;
}



// game classes
function tabletopObject(y,x,type,img){
	this.x = x;
	this.y = y;
	this.w = 1;
	this.h = 1;
	this.type = type
	if( this.type == 'building' ){
		this.parent = tabletopDraw.oBuildings;
	}else { //if( this.type == 'unit' ){
		this.parent = tabletopDraw.oUnits;
	}
	this.index = -1;
	this.img = img
	this.type = 'none';
	this.createElements();
}
tabletopObject.prototype.createElements = function(){
	this.obj = document.createElement('IMG');
	this.obj.style.position = 'absolute';
	this.obj.src = 'img/'+this.img;
	this.obj.id = this.type + this.index;
	this.hide();
	this.parent.appendChild(this.obj);
}
tabletopObject.prototype.show = function(){
	this.obj.style.top = (this.y - tabletopDraw.visibleMapTop) * tabletopDraw.tileHeight;
	this.obj.style.left = (this.x - tabletopDraw.visibleMapLeft) * tabletopDraw.tileWidth;
	this.obj.style.display = 'inline';
	Debug(this.obj.style);
}
tabletopObject.prototype.hide = function(){
	this.obj.style.display = 'none';
}






function tabletopBuilding(x, y, img){
	return new tabletopObject(y,x, 'building', img);
}
function tabletopUnit(x, y, img){
	return new tabletopObject(y,x, 'unit', img);
}




function Castle(y,x){
	var o = new tabletopBuilding(y, x, 'castle.gif');
	o.w = 2;
	o.h = 2;
	return o;
}
function Infrantry(y,x) {
	return new tabletopUnit(y, x, 'swordswoman.png');
}
Infrantry.prototype.hide = function(){
	alert("nada feito");
}
function Archer(y,x) {
	return new tabletopUnit(y, x, 'archer.gif');
	this.x = x;
	this.y = y;
	this.type = 'img/archer.gif';
}







// ========================= DISPATCHER ====================
tabletopDispatcher = {
	eventQueue : [],
	mouseLastX : 0,
	mouseLastY : 0,
	initialize : function(){
		tabletopGame.initialize();
		//hook up events
		window.onmousemove = this.mouseMoveHook;
		window.onmouseclick = this.mouseClickHook;
		window.onblur = this.blurHook;
		this.startTimer();
	},
	startTimer : function(){
		this.intervalHandle = window.setInterval( tabletopDispatcher.mainLoop, 250);
	},
	stopTimer : function(){
		window.clearInterval( this.intervalHandle );
	},
	// ----------------- event hooks ------------------
	// use the object name instead of 'this'. we will
	// be out of the scope.
	// damn javascript lack of references
	blurHook : function(e){
		tabletopDispatcher.mouseLastY = -1;
		tabletopDispatcher.mouseLastX = -1;
	},
	mouseClickHook : function(mouseEvent){
		tabletopDispatcher.eventQueue.push( mouseEvent );
	},
	mouseMoveHook : function(mouseEvent){
		// this function is passed by value to the window object
		// so we run off the class scope.
		//tabletopDispatcher.eventQueue = mouseEvent //i like short queues
		if(mouseEvent.clientY < 1) return;
		if(mouseEvent.clientX < 1) return;
		tabletopDispatcher.mouseLastY = mouseEvent.clientY;
		tabletopDispatcher.mouseLastX = mouseEvent.clientX;
		window.onmousemove = tabletopDispatcher.mouseMoveHook;
	},
	// ----------------- interval hooks --------------------
	mainLoop : function(){
		// this function is passed by value to the setInterval method
		// so we run off the class scope.
		//tabletopDispatcher.stopTimer();
		//mouseEvent = tabletopDispatcher.eventQueue;
		if( tabletopDispatcher.mouseLastY <0 && tabletopDispatcher.mouseLastX <0 ){
			return;
		}

		if( tabletopDispatcher.eventQueue.length > 0 ){
			// TODO: pass to something more usefull then debug
			Debug( tabletopDispatcher.eventQueue.pop() );
		}
		tabletopDraw.mouseMoveEvent( tabletopDispatcher.mouseLastY, tabletopDispatcher.mouseLastX );
		//tabletopDispatcher.startTimer();
	},
FIM:'DISPATCHER'}



// ========================== GAME ===============================
tabletopGame = {
	server : 'http://localhost/tabletopengine/server.py/',
	mapWidth : 500,
	mapHeight : 500,
	buildings : [],
	units : [],

	initialize : function(){ // ------------------------------ constructor
		// initialize the graphic engine
		tabletopDraw.initialize();
		// get server data
		this.loadMap();
		this.loadBuildings();
		this.loadUnits();
		// center the view in the player start point
		tabletopDraw.centerMap(100,100);
	},
	loadBuildings : function(){ // ---------------------------- load buildings
		b1 = new Castle(100,100);
		b1.index = 0;
		this.buildings = [b1];
	},
	loadUnits : function(){ // --------------------------- load units
		i1 = new Infrantry(99,99);
		i1.index = 0;
		i2 = new Archer(101,101);
		i2.index = 1;
		i2.selected = true;
		this.units = [i1,i2];
	},
	loadMap : function(){
		/* we should already have a map var, from a js.
		 *  the file should be around 500^2 bytes. assuming w500 and h500.
		 * let's pray every client have gzip compression!
		 */
		this.map = mapfloor;

		// hack
		// randomize some dirty patches on the green grass so it's easier to see map movement.
		// ideally this should be  hardcoded on the fakeMapjs... but this way is easier
		for( var x=0; x<= this.map.length; x++ ){
			if( this.map[x] )
			for( var y=0; y<= this.map[0].length; y++ ){
				if( this.map[x][y] == 0 ){
					if( Math.random() > 0.6 ){
						this.map[x][y] = 'b';
					}
				}
			}
		}
		// end of hack
	},
FIM : 'Game'}

// ============================================== DRAW ================================
// this is the drawing engine.
tabletopDraw = {
	// "constants"
	tileWidth : 48, // TODO: this should be calculated on the fly based on container size on the page.
	tileHeight : 48, //      or maybe not... game fairnes vs spifines
	visibleMapWidth : 10,
	visibleMapHeight : 10,
	// properties
	visibleMapTop : 0,
	visibleMapLeft : 0,
	initialize : function(){
		// externals
		this.oBoard = document.getElementById('tabletopBoard');
		this.oSelection = document.getElementById('tabletopSelection');
		this.oBuildings = document.getElementById('tabletopBuildings');
		this.oUnits = document.getElementById('tabletopUnits');
		// temp. the select image... that will evolve later
		this.oSelection.style.backgroundImage = "url(img/selected.png)";
		this.oSelection.style.backgroundRepeat = "no-repeat";
		this.oSelection.style.width = this.tileWidth + "px";
		this.oSelection.style.height = this.tileHeight + "px";
		this.oSelection.style.position = "absolute";

		// initialize map elements
		this.drawMap();
	},
	mouseMoveEvent : function( y, x, button ){
		y = y;
		x = x;
		mapRight = this.visibleMapWidth * this.tileWidth;
		mapBottom = this.visibleMapHeight * this.tileHeight;
		//move the view?
		newViewY = this.visibleMapTop;
		newViewX = this.visibleMapLeft;
		newView = false;
		if( y < this.tileHeight && y > -30 ){
			newViewY--;
			newView = true;
		}else if( y > (mapBottom - this.tileHeight) && y < (mapBottom + 30)){
			newViewY++;
			newView = true;
		}else if( y < 0 || y > mapBottom ){ // it's outside of the map
			return;
		}
		if( x < this.tileWidth && x > -30 ){
			newViewX--;
			newView = true;
		}else if( x > (mapRight - this.tileWidth) && x < (mapRight + 30)){
			newViewX++;
			newView = true;
		}else if( x < 0 || x > mapRight){ // it's outside of the map
			return;
		}
		if( newView ){
			this.moveMap( newViewY, newViewX );
			return; // no need to continue, cursor is obviously off the map
		}
		
		//get tile mouse is over
		mapX = Math.floor(x / this.tileWidth) + this.visibleMapLeft;
		mapY = Math.floor(y / this.tileHeight) + this.visibleMapTop;

		// TODO: ativar o evento de "mouse se mexeu no mapa" apenas se o valor for
		// diferente do anterior. ou se o mapa for redesenhado (pois ele pode ter
		// se mexido e agora o mouse esta sobre outra coisa)
		this.setMouseOver(mapY, mapX);
	},
	setMouseOver : function( y, x ){
		this.mouseX = x;
		this.mouseY = y;
		this.oSelection.style.top = ( ( y - this.visibleMapTop) * this.tileHeight);
		this.oSelection.style.left = ( ( x - this.visibleMapLeft) * this.tileWidth);

	},
/* redraw the map */
	drawMap : function(){
		// simply create the initial elements that centerMap() will use
		this.tile = Array(this.visibleMapHeight)
		for( var y = 0; y < this.visibleMapHeight; y++ ){
			this.tile[y] = Array(this.visibleMapWidth);
			for( var x = 0; x < this.visibleMapWidth; x++ ){
				tabletopDraw.addTile( y, x);
			}
		}
	},
	centerMap : function( y, x ){ 
		// get the top left corner
		topY = y - Math.floor(this.visibleMapHeight/2);
		topX = x - Math.floor(this.visibleMapWidth/2);
		this.moveMap(94, 95);
	},
	moveMap : function( y, x ){ // move maptop to cordinates
		// TODO: hideElements can go into showElements, so we  save one loop
		this.hideElements();
		this.visibleMapTop = y;
		this.visibleMapLeft = x;
		// essa linhas devem estar aqui? acho q casa mais com a centerMap...
		if( this.visibleMapTop < 0 ) this.visibleMapTop = 0;
		if( this.visibleMapLeft < 0 ) this.visibleMapLeft = 0;
		if( this.visibleMapTop > this.mapHeight ) this.visibleMapTop = this.mapHeight - this.visibleMapHeight;
		if( this.visibleMapLeft > this.mapWidth ) this.visibleMapLeft = this.mapWidth - this.visibleMapWidth;
		// chage the images acording to the map data
		for( var y = 0; y < this.visibleMapHeight; y++ ){
			for( var x = 0; x < this.visibleMapWidth; x++ ){
				this.tile[y][x].style.backgroundImage = 'url(img/'+tabletopGame.map[this.visibleMapTop+y][this.visibleMapLeft+x]+'.png)';
			}
		}
		this.showElements();
	},
	hideElements : function(){
		for( curinga in {'units':0,'buildings':0} ){
			for( uIndex in tabletopGame[curinga] ){
				u = tabletopGame[curinga][uIndex];
				u.hide();
			}
		}
	},
	showElements : function(){
		//loop the units and buildings to see if there's something to show
		for( curinga in {'units':0,'buildings':0} ){
			for( uIndex in tabletopGame[curinga] ){
				u = tabletopGame[curinga][uIndex];
				if(   (
					      (u.x + u.w) >= this.visibleMapLeft
					   && u.x - 1 < (this.visibleMapLeft + this.visibleMapWidth)
					  )
					 && (
					      (u.y + u.h) >= this.visibleMapTop
					   && u.y - 1 < (this.visibleMapTop + this.visibleMapHeight)
					  )
				){
					u.show();
				}
			}
		}
	},
	addTile : function( y, x ){
		obj = document.createElement('DIV');
		obj.style.background = '#000';
		obj.style.position = 'absolute';
		obj.style.width = this.tileWidth + 'px';
		obj.style.height = this.tileHeight + 'px';
		obj.style.left = (x * this.tileWidth);
		obj.style.top = (y * this.tileHeight);
		this.oBoard.appendChild(obj);
		this.tile[y][x] = obj
	},
FIM:"DRAW"}

bodyLoadEvent = function(){
	tabletopDispatcher.initialize();
}
